﻿/*
 * Created by SharpDevelop.
 * User: it1050
 * Date: 29/03/11
 * Time: 21:24
 * 
 * To change this template use Tools | Options | Coding | Edit Standard Headers.
 */
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;
using PdfSharp;
using PdfSharp.Pdf;
using PdfSharp.Pdf.IO;
using org.pdfbox.util;
using org.pdfbox.pdmodel;
using IniFiles;
using MailHandle;

namespace MailInvoice
{
  /// <summary>
  /// Description of MainForm.
  /// </summary>
  public partial class MainForm : Form
  {
    string vTempPath; //path per la cartella temporanea in cui copiare i file ed eseguire i job
    
    public MainForm()
    {
      //
      // The InitializeComponent() call is required for Windows Forms designer support.
      //
      InitializeComponent();
      
    } //MainForm()
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// Apro il file pdf da elaborare
    /// </summary>
    void BtnOpenFileClick(object sender, EventArgs e)
    {
      dlgOpenFile.Title="select file";
      if (dlgOpenFile.ShowDialog() == DialogResult.OK)
        edtPDFFile.Text = dlgOpenFile.FileName.ToString();
    } // BtnOpenFileClick
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// lancio le procedure
    /// </summary>
    void BtnRunClick(object sender, EventArgs e)
    {
      //pulisco il log
      edtLog.Text="";
      
      //Splitto il pdf in pagine singole nella subdir temp
      _fSplitFile(edtPDFFile.Text);
      
      //MessageBox.Show(fReadFile(edtPDFFile.Text));
      MessageBox.Show("Done", "Result", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1,0);
    } // BtnRunClick
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    ///enable-disable email invoicing
    /// </summary>
    void ChkEmailCheckedChanged(object sender, EventArgs e)
    {
      pnlMail.Enabled = chkEmail.Checked;
    }
    //-------------------------------------------------------------------------------------------------------//   
    void MainFormLoad(object sender, EventArgs e)
    {
      //carico i dati dal file ini
      _fReadINI();
    }
    //-------------------------------------------------------------------------------------------------------//   
    /// <summary>
    /// prendo il file pdf e lo decomprimo suddividendolo in singole pagine
    /// </summary>
    /// <param name="pFname">nome file da elaborare</param>
    void _fSplitFile(string _pFname)
    {
      string vOutFname="";    //fileName in output x splitting
      string vTxtRead="";     //estrazione dati in formato testo dal PDF
      string vOutFRename="";  //fileName in output
      string[] vFileArr=new string[50];//array stringa per la ricompattazione del file
      string vKeyMerge="";    //var di controllo per verificare il cambio del documento
      int vKeySrcIdx=0;       //indice per ricerca substring codice cliente-fattura
      int vPagesIdx=0;        //indice per l'array delle pagine
      
      if (string.IsNullOrEmpty(_pFname))
        MessageBox.Show("PDF File Missed!","ATTENZIONE!!",MessageBoxButtons.OK,MessageBoxIcon.Error, MessageBoxDefaultButton.Button1,0);
      
      //build temp path
      
      vTempPath=Path.GetDirectoryName(Application.ExecutablePath)+"\\temp\\";
      _fLog("-- Checking temp dir... "+ vTempPath);
      //edtLog.Text+=DateTime.Now.ToString()+"-- Checking temp dir... "+ vTempPath+" \r\n";
      if (!System.IO.Directory.Exists(vTempPath))
      {
        //edtLog.Text+=DateTime.Now.ToString()+"-- Folder not found... Creating"+" \r\n";
        _fLog("-- Folder not found... Creating");
        System.IO.Directory.CreateDirectory(vTempPath);
      }
      
      // Open the file
      PdfDocument inputDocument = PdfReader.Open(_pFname, PdfDocumentOpenMode.Import);
      Application.DoEvents();
      //edtLog.Text+=DateTime.Now.ToString()+"-- Open PDF File " + pFname+" \r\n";
      _fLog("-- Open PDF File " + _pFname);

      string vName = Path.GetFileNameWithoutExtension(_pFname);
      for (int idx = 0; idx < inputDocument.PageCount; idx++)
      {
        // Create new document
        //edtLog.Text+=DateTime.Now.ToString()+String.Format(CultureInfo.InvariantCulture,"-- Processing page {0}",idx + 1)+" \r\n";
        _fLog(String.Format(CultureInfo.InvariantCulture,"-- Processing page {0}",idx + 1));

        PdfDocument outputDocument = new PdfDocument();
        outputDocument.Version = inputDocument.Version;
        outputDocument.Info.Title = String.Format(CultureInfo.InvariantCulture,"Page {0} of {1}", idx + 1, inputDocument.Info.Title);
        outputDocument.Info.Creator = inputDocument.Info.Creator;

        // Add the page and save it
        outputDocument.AddPage(inputDocument.Pages[idx]);
        vOutFname = String.Format(CultureInfo.InvariantCulture,vTempPath+"{0}-Page-{1:000}.pdf", vName, idx + 1);
        outputDocument.Save(vOutFname);
        Application.DoEvents();
        
        // leggo il contenuto del file
        vTxtRead=_fReadFile(vOutFname);
        // cerco all'interno della stringa il substring "xk" che delimita l'inizio
        //   del codice utente e nr fattura
        vKeySrcIdx=vTxtRead.IndexOf(@"xk", StringComparison.CurrentCultureIgnoreCase);
        if (vKeySrcIdx!=-1) //Rinomino il file
        {
          //28.04.11-vOutFRename=vTempPath+String.Format(CultureInfo.InvariantCulture, vTxtRead.Substring(vKeySrcIdx+3,15)+"-{0:000}.pdf", idx + 1);
          // correzione bug nel caso in cui il nome file contegna caratteri illegali "\*:....."
          
          vOutFRename=_fRemoveSpecialChars(String.Format(CultureInfo.InvariantCulture, vTxtRead.Substring(vKeySrcIdx+3,15)+"-{0:000}.pdf", idx + 1));
          vOutFRename=vTempPath+vOutFRename;
          
          if (File.Exists(vOutFRename)) File.Delete(vOutFRename);
          File.Move(vOutFname, vOutFRename);
          //verifico se si stia cmabiando documento e si debbano quindi compattare i file pdf generati sinora
          if ((idx != 0) && (_fRemoveSpecialChars(vTxtRead.Substring(vKeySrcIdx+3,15)) != vKeyMerge) )
          {
            //richiamo la creazione del file che ragrruppa la singola fattura
            _fMakeSingle(vFileArr, vTempPath+vKeyMerge, true, true);
            // TODO: invio mail
            
            //reinizializzo l'array
            Array.Clear(vFileArr,0,vFileArr.Length);
            //reinizializzo il contatore per le pagine
            vPagesIdx=0;
          }
          
          //aggiungo all'array il documento successivo
          vFileArr[vPagesIdx] = vOutFRename;
          
          //se sono all'ultima pagina del documento devo considerare di forzare la compattzione anche se il keymerge non varia
          //   ciò è dovuto al fatto che poi il ciclo si concluderebbe
          if (idx == inputDocument.PageCount-1)
            _fMakeSingle(vFileArr, vTempPath+vKeyMerge, true, true);
          
          vKeyMerge = _fRemoveSpecialChars(vTxtRead.Substring(vKeySrcIdx+3,15)); //imposto il valore x il controllo
          vPagesIdx++; //aggiorno il contatore per le pagine
        }
      } // for sullo split dei file

      //ricompatto i file in un unico pdf pronto per la stampa e riordinato per cliente-fattura
      //edtLog.Text+=DateTime.Now.ToString()+"-- Creating Final File.... "+" \r\n";
      _fLog("-- Creating Final File.... ");
      
      //raggruppo le singole fatture nel file finale
      _fProcessSplittedFiles();
      //edtLog.Text+=DateTime.Now.ToString()+"-- All Done!!"+" \r\n";
      _fLog("-- All Done!!");
      
    } // SplitFile()
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// leggo il file pdf e ne estraggo il contenuto di testo ritornandolo come risultato della funzione
    /// </summary>
    /// <param name="pFname">nome file pdf da cui estrarre il test</param>
    /// <returns>file completo convertito in testo</returns>
    string _fReadFile(string _pFname)
    {
      string vResult="";
      string strExtension = _pFname.Substring(_pFname.LastIndexOf(".", StringComparison.CurrentCultureIgnoreCase) + 1);
      //Validate filetype
      if (strExtension.ToUpper(CultureInfo.CurrentCulture) != "PDF")
        MessageBox.Show( "Please select a PDF file", "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1,0);
      else
      {
        //User interface status updates
        Cursor = Cursors.WaitCursor;
        //edtLog.Text += DateTime.Now.ToString()+"-- Extracting text...please wait..."+" \r\n";
        _fLog("-- Extracting text...please wait...");
        Application.DoEvents();
        try
        {
          //Extract text from PDF file
          PDDocument objDocument = PDDocument.load(_pFname);
          Application.DoEvents();
          PDFTextStripper objTextStripper = new PDFTextStripper();
          vResult = objTextStripper.getText(objDocument);
        }
        catch (Exception ex)
        {
          vResult = "Exception: " + ex.Message;
        }
        //Restore cursor
        Cursor = Cursors.Default;
      }
      return vResult;
    } // fReadFile
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// Compatta i filepassati nell'array in un unico pdf
    /// </summary>
    /// <param name="pFilesArr">elenco filenames da compattare</param>
    /// <param name="pOutFname">nome del file di output</param>
    /// <param name="pDeleteOrigFiles">elimina i file singoli utilizzati per la compattazione</param>
    /// <param name="pFR">elbora il file per il fronte retro</param>
    void _fMakeSingle(string[] _pFilesArr, string _pOutFname, bool _pDeleteOrigFiles, bool _pFR)
    {
      // ciclo sui file passati come parametro in array e creo un file nominato dal nr fattura
      //   ed elimino i file di origine
      
      // Open the output document
      PdfDocument outputDocument = new PdfDocument();
      
      // Iterate files
      foreach (string file in _pFilesArr)
      {
        // chk if string is not empty
        if (!string.IsNullOrEmpty(file))
        {
          // Open the document to import pages from it.
          PdfDocument inputDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);
          // Iterate pages
          int count = inputDocument.PageCount;
          for (int idx = 0; idx < count; idx++)
          {
            // Get the page from the external document...
            PdfPage page = inputDocument.Pages[idx];
            // ...and add it to the output document.
            outputDocument.AddPage(page);
          }
          //delete original file
          if (_pDeleteOrigFiles)
            File.Delete(file);
        }
      }
      //verifico che il nr delle pagine del documento siano pari per permettere la stampa fronte/retro del documento
      if (_pFR)
        if (outputDocument.PageCount%2 != 0) //nr pagine dispari e quindi aggiungo una pagina vuota
      {
        PdfPage vFillerPAge = outputDocument.AddPage();
        vFillerPAge.Orientation = PageOrientation.Landscape;
      }
      // Save the document...
      // 27.04.11 - sistemato il problema della doppia estensione --outputDocument.Save(pOutFname+".pdf");
      outputDocument.Save(_pOutFname+".pdf");
      //edtLog.Text+=DateTime.Now.ToString()+"-- Compacting file -> "+pOutFname+".pdf"+ " \r\n";
      _fLog("-- Compacting file -> "+_pOutFname+".pdf");
      
    } // _fMakeInvoiceFile
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// creo il file finale totale da mandare in stampa fronte/retro
    /// </summary>
    void _fProcessSplittedFiles()
    {
      //recupero l'elenco completo dei file della cartella temp
      string[] vFiles = Directory.GetFiles(vTempPath);
      
      //richiamo la creazione del file che ragrruppa la singola fattura
      _fMakeSingle(vFiles, Path.GetDirectoryName(edtPDFFile.Text)+@"\"+Path.GetFileNameWithoutExtension(edtPDFFile.Text)+"_TO_PRINT.pdf", true, false);

    }  // _fProcessSplittedFiles
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// inserisco nella textbox il log delle operazioni eseguite e mi sposto all'ultima linea
    /// </summary>
    /// <param name="_pString"> testo da inserire </param>
    void _fLog(string _pString)
    {
      //aggiungo la linea anteponendo data e ora
      edtLog.Text+=DateTime.Now.ToString()+" -- " + _pString +" \r\n";
      //mi sposto alla fine dello scroll
      edtLog.Select(edtLog.Text.Length - 1, 0);
      edtLog.ScrollToCaret();
    } // _fLog
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// Legge il file ini ed inserisce i valori nella mask 
    /// </summary>
    void _fReadINI()
    {
      string _vIniFName=Path.ChangeExtension(Path.GetFullPath(Application.ExecutablePath), "ini");
      IniFile _vIni   = new IniFile(_vIniFName);
      edtSMTP.Text    = _vIni.IniReadValue("Mail","SMTPServer");
      edtSubject.Text = _vIni.IniReadValue("Mail","Subject");
      edtUser.Text    = _vIni.IniReadValue("Mail","User");
      edtSender.Text  = _vIni.IniReadValue("Mail","Sender");

      //ini.IniWriteValue("Info","LastName",lname.Text);
    } // _fReadINI
    //-------------------------------------------------------------------------------------------------------//
    /// <summary>
    /// Ripulisce le stringhe dai caratteri indicati nella funzione
    /// </summary>
    /// <param name="_pStr"> stringa da valutare</param>
    /// <returns> stringa "ripulita" </returns>
    string _fRemoveSpecialChars(string _pStr)
    {
      string[] chars = new string[]{"\"","\\","\r","\n",",","/","!","@","#","$","%","^","&","*","'",";","_","(",")",":","|","[","]"};
      for(int i = 0; i< chars.Length; i++ )
      {
        if(_pStr.Contains(chars[i]))
          _pStr = _pStr.Replace(chars[i],"");
      }
      return _pStr;
    } // _fRemoveSpecialChars
    //-------------------------------------------------------------------------------------------------------//
    void _fMailDelivery(string _pFName)
    {
      //leggo il file con gli indirizzi mail e lo carico in un array

//      ArrayList items = new ArrayList();
//      StreamReader reader = new StreamReader(filename);
//      int numItems = int.Parse(reader.ReadLine());
//      for (int i=0; i < numItems; i++) 
//      {
//        items.Add(reader.ReadLine());
//      }
//      reader.Close();
//      return items;

      //cerco il codice nel file
    
   
    //richiamo la funzione di invio mail
     
    } //_FMailDelivery()
    //-------------------------------------------------------------------------------------------------------//
  } // class MainForm : Form
}
